package com.bkhc.common.util;


import com.bkhc.common.annotation.ApiOperation;
import com.bkhc.common.entity.ApiInfo;
import com.bkhc.common.entity.ApiPack;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.*;

/**
 * @author lb
 * @date 2021/4/24
 * @time 0:36
 */

public class ReadAnnotationUtils {
    private static final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    private static final SimpleMetadataReaderFactory register = new SimpleMetadataReaderFactory();
    private static final StandardEnvironment environment = new StandardEnvironment();
    /**
     * 根据包路径,获取Class的资源路径
     *
     * @param packagePath
     * @return
     */
    public static String getResourcePath(String packagePath) {
        if (StringUtils.isEmpty(packagePath)) return "";
        String resourcePath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(environment.resolveRequiredPlaceholders(packagePath))
                + '/' + "**/*.class";
        return resourcePath;
    }
    /**
     * 获取指定路径下的类的操作
     *
     * @param pkgPath
     * @param annoClazz
     * @return
     */
    public static Set<ApiPack> getClazzFromAnnotationOperation(String pkgPath, Class <?extends Annotation> annoClazz) {
        //获取spring的包路径
        String pathPackage = getResourcePath(pkgPath);
        Set<ApiPack> packs = new HashSet<ApiPack>();
        Resource[] resources = new Resource[0];
        try {
            //加载路径
            resources = resolver.getResources(pathPackage);
        } catch (IOException e) {
            //异常处理
            return new HashSet<>();
        }
        for (int i = 0; i < resources.length; i++) {
            Resource resource = resources[i];
            MetadataReader metadataReader = null;
            try {
                //读取资源
                metadataReader = register.getMetadataReader(resource);
            } catch (IOException e) {
                continue;
            }
            //读取资源的注解配置
            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            //判断是否包含注解
            if (!annotationMetadata.hasAnnotation(annoClazz.getName())) continue;
            if (!annotationMetadata.hasAnnotation(RequestMapping.class.getName())) continue;
            //类信息
            Map<String, Object> apiServicePack = annotationMetadata.getAnnotationAttributes(annoClazz.getName());
            ApiPack pack = new ApiPack();
            pack.setCode(apiServicePack.get("code").toString());
            pack.setName(apiServicePack.get("name").toString());
            pack.setDescription(apiServicePack.get("description").toString());
            pack.setCreator("system");
            pack.setUpdator("system");
            Map<String, Object> apiServicePackMapping = annotationMetadata.getAnnotationAttributes(RequestMapping.class.getName());
            String[] apipackageurls = (String[]) apiServicePackMapping.get("path");
            if (!annotationMetadata.hasAnnotatedMethods(ApiOperation.class.getName())) continue;
            Set<MethodMetadata> methods = annotationMetadata.getAnnotatedMethods(ApiOperation.class.getName());
            List<ApiInfo> operations = new ArrayList<ApiInfo>();
            for (MethodMetadata metadata : methods) {
                if(metadata.isAnnotated(RequestMapping.class.getName())&&metadata.isAnnotated(ApiOperation.class.getName())){
                    Map<String, Object> attributes = metadata.getAnnotationAttributes(ApiOperation.class.getName());
                    ApiInfo operation = new ApiInfo();
                    operation.setCode(attributes.get("code").toString());
                    operation.setName(attributes.get("name").toString());
                    operation.setDescription(attributes.get("description").toString());
                    operation.setApiPackage(pack.getCode());
                    operation.setApiType(attributes.get("type").toString());
                    metadata.isAnnotated(RequestMapping.class.getName());
                    Map<String, Object> urlmap = metadata.getAnnotationAttributes(RequestMapping.class.getName());
                    String[] urls = (String[]) urlmap.get("path");
                    operation.setApi(urls[0]);
                    if(apipackageurls.length>0){
                        operation.setApi(apipackageurls[0]+urls[0]);
                    }

                    RequestMethod[] requestMethod = (RequestMethod[])urlmap.get("method");
                    operation.setRequestType(requestMethod[0].name());
                    operation.setCreator("system");
                    operation.setUpdator("system");
                    operations.add(operation);
                }


            }
            pack.setApis(operations);
            packs.add(pack);
        }
        return packs;
    }
}
